﻿#include "include/CUtils.h"
#include <sstream>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <QByteArray>
#include <QString>
#include <QUuid>
#include <QDir>
#include <QFileInfo>
BASELIB_BEGIN_NAMESPACE


CUtils::CUtils()
{

}

CUtils::~CUtils()
{

}


string CUtils::strReplaceAllword(const string& resources,const string &key, const string& ReplaceKey)
{
		size_t pos=0;
		string temp = resources;
		while((pos=temp.find(key,pos))!=string::npos)
		{
			temp.erase(pos, key.size());
			temp.insert(pos, ReplaceKey);
			pos+= ReplaceKey.size();
		}
		return temp;
}


void CUtils::unescapeC(string &resources)
{
	size_t pos=0;
	while((pos=resources.find("\\",pos))!=string::npos)
	{
		resources.erase(pos,1);
		pos += 1;
	}
}

bool CUtils::getCpuId(string& strCpuId)
{
    QByteArray uniqueId = QSysInfo::machineUniqueId();
    QString id = QString::fromLatin1(uniqueId.toHex());
    strCpuId = "win"+id.toStdString();
    return true;
}


// 判断IP地址的合法性
bool CUtils::isValidIP(string pcIp)
{
	// 为空返回不合法
	if(pcIp.empty())
		return false;
	
	// 查找是否有除数字和.之外的其他字符，如果有返回不合法
	for(int i = 0; i < pcIp.size(); i++){
		if((pcIp.at(i) < '0' && pcIp.at(i) != '.') || pcIp.at(i) > '9' ){
			return false;
		}
	}

	vector<string> list = CUtils::split(pcIp, ".");

	// 按照.分割，如果不等于4个返回不合法
	if(list.size() != 4){
		return false;
	}

	// 例:a.b.c.d
	// 挨个判断是否合乎标准
	for(int i = 0; i < 4; i++){
		// 只要有一个为空就返回不合法
		if(list.at(i).empty()){
			return false;
		}
		if(i == 0){
			// a不能为0或者0x或者0xx
			if(atoi(list.at(i).c_str()) == 0 || list.at(i).at(0) == '0'){
				return false;
			}
		}
		else {
			// b c d不能0x或者0xx
			if(	(atoi(list.at(i).c_str()) == 0 && list.at(i).size() > 1)
					|| (atoi(list.at(i).c_str()) != 0 && list.at(i).at(0) == '0')
					){
				return false;
			}
		}
		// a b c d不能大于255或者小于0
		if(atoi(list.at(i).c_str()) < 0 || atoi(list.at(i).c_str()) > 255){
			return false;
		}
	}
	return true;
}

bool CUtils::isDhcp(bool *isDhcp)
{
	char str[100];
	char *c;
	FILE* file = fopen("/data/etc/interfaces", "r");
	if (!file) {
		return false;
	}
	//iface eth0 inet dhcp
	//iface eth0 inet static
	while (fgets(str, 199, file))
	{
		c = str;
		// 鍘绘帀鍓嶉潰绌烘牸
		while (*c == ' ') c++;
		if (*c != '#') {
			if (strstr(c, "iface eth0 inet dhcp")) {
				*isDhcp = true;
				fclose(file);
				return true;
			}
			if (strstr(c, "iface eth0 inet static")) {
				*isDhcp = false;
				fclose(file);
				return true;
			}
		}
	}
	fclose(file);
	return false;
}

bool CUtils::checkMacAddr(const char *mac)
{
	char mac_addr_string[50];
	strcpy(mac_addr_string, mac);
	if (strlen(mac_addr_string) != 17)
		return false;

	char *strtmp = strtok(mac_addr_string, ":");

	int hexnum = 0;

	while (strtmp != NULL)
	{
		if (strlen(strtmp) != 2) return false;

		if ((strtmp[0] >= '0' && strtmp[0] <= '9') || (strtmp[0] >= 'A' && strtmp[0] <= 'F') || (strtmp[0] >= 'a' && strtmp[0] <= 'f'))
		{
			if ((strtmp[1] >= '0' && strtmp[1] <= '9') || (strtmp[1] >= 'A' && strtmp[1] <= 'F') || (strtmp[1] >= 'a' && strtmp[1] <= 'f'))
			{
				hexnum++;
				strtmp = strtok(NULL, ":");
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}

	}
	if (hexnum != 6)
		return false;

	return true;
}

int CUtils::createMultiLevelDir(char* sPathName)
{
	char DirName[256];
	int i, len;

	strcpy(DirName, sPathName);
	len = strlen(DirName);
	if ('/' != DirName[len - 1]) {
		strcat(DirName, "/");
		len++;
	}

	for (i = 1; i < len; i++)
	{
		if ('/' == DirName[i])
		{
			DirName[i] = '\0';

            QFileInfo fileInfo(DirName);
            if(!fileInfo.exists())
                QDir().mkdir(DirName);
			DirName[i] = '/';
		}
	}

	return 0;
}

string CUtils::hexToString(uint8_t *pucBuf, uint16_t usLen, bool isCapitalize)
{
	stringstream sstr;
	char str[3] = { 0 };
	uint16_t i, j;

	for (i = 0; i < usLen; i++) {
		sprintf(str, "%02x", pucBuf[i]);	//鏍煎紡鍖栨垚瀛楃涓�
		if(isCapitalize){
			for (j = 0; j < 2; j++) {
				str[j] = toupper(str[j]);	//杞ぇ鍐�
			}
		}
		sstr << str;
	}
	return sstr.str();
}

uint16_t CUtils::stringToHex(string *str, uint8_t *pucBuf, uint16_t usLen)
{
	if(usLen < 1){
		return 0;
	}
	uint16_t i;
	uint8_t *pEnd = pucBuf + (usLen-1);
	uint8_t data[2];

	if (str->length() % 2) {
		str->insert(0, "0");
		printf("str->insert(0,0)\r\n");
		printf("str->%s\r\n", str->c_str());
	}
	for (i = 0; i < str->length(); i += 2) {
		if (str->data()[i] >= 'A') {
			data[0] = str->data()[i] - 'A' + 0xa;
		}
		else {
			data[0] = str->data()[i] - '0';
		}

		if (str->data()[i + 1] >= 'A') {
			data[1] = str->data()[i + 1] - 'A' + 0xa;
		}
		else {
			data[1] = str->data()[i + 1] - '0';
		}

		*pucBuf = data[0] << 4 | data[1];
		pucBuf++;
		if (pucBuf > pEnd)
			return usLen;
	}
	return i / 2;
}

int CUtils::htoi(unsigned char *s)
{
	int i;
	int n = 0;
	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) //鍒ゆ柇鏄惁鏈夊墠瀵�x鎴栬�0X
	{
		i = 2;
	} else {
		i = 0;
	}
	for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'); ++i)
	{
		if (tolower(s[i]) > '9')
		{
			n = 16 * n + (10 + tolower(s[i]) - 'a');
		} else {
			n = 16 * n + (tolower(s[i]) - '0');
		}
	}
	return n;
}

/**
* rec_ucCheckXor 寮傛垨鏍￠獙
* 鍙傛暟锛�pBuf鈥斺�褰撳墠鏁版嵁缂撳啿鍖烘寚閽�
*       len鈥斺�鏁版嵁闀垮害
* 杩斿洖锛氳绠楃粨鏋�
**/
uint8_t CUtils::ucBufCheckXor(uint8_t *pucBuf, uint16_t usLen)
{
	uint8_t ucCheckXor = 0;
	while (usLen--)
		ucCheckXor ^= *pucBuf++;
	return  ucCheckXor;
}


/**
* rec_check sum 姹傚拰
* 鍙傛暟锛�pBuf鈥斺�褰撳墠鏁版嵁缂撳啿鍖烘寚閽�
*       len鈥斺�鏁版嵁闀垮害
* 杩斿洖锛氳绠楃粨鏋�
**/
uint8_t CUtils::ucBufCheckSum(uint8_t *pucBuf, uint16_t usLen)
{
	uint8_t checkSum = 0;
	while (usLen--)
		checkSum += (uint8_t)*pucBuf++;
	return  checkSum;
}

/**
* rec_check sum 求和
* 参数：*pBuf——当前数据缓冲区指针
*       len——数据长度
* 返回：计算结果
**/
uint16_t CUtils::ucBufCheckSum16(uint8_t *pucBuf, uint16_t usLen)
{
	uint16_t checkSum = 0;
	while (usLen--)
		checkSum += (uint8_t)*pucBuf++;
	return  checkSum;
}

/**
* rec_check sum 姹傚拰
* 鍙傛暟:*pBuf褰撳墠鏁版嵁缂撳啿鍖烘寚閽�
*       len鏁版嵁闀垮害
* 杩斿洖:璁＄畻缁撴灉
**/
uint32_t CUtils::uiBufCheckSum(uint8_t *pucBuf, uint16_t usLen)
{
	uint32_t uiCheckSum = 0;
	while (usLen--)
		uiCheckSum += (uint32_t)*pucBuf++;
	return  uiCheckSum;
}


//字符串分割函数
vector<string> CUtils::split(string str, string pattern)
{
    string::size_type pos;
    vector<string> result;
    str += pattern;//扩展字符串以方便操作
    int size = str.size();
    for (int i = 0; i < size; i++)
    {
        pos = str.find(pattern, i);
        if (pos < size)
        {
            string s = str.substr(i, pos - i);
            if(!s.empty()){
                result.push_back(s);
            }
            i = pos + pattern.size() - 1;
        }
    }
    return result;
}


// list转字符串
string CUtils::listToStdString(const list<string> & listAddr, const string &pattern)
{
	string ret;
	for(auto & i : listAddr){
		if(ret.empty()){
			ret = i;
			continue;
		}
		ret += pattern + i;
	}
	return ret;
}


// 字符串转list
list<string> CUtils::stdStringToList(string listAddr, const string &pattern)
{
    string::size_type pos;
    list<string> result;
    listAddr += pattern;//扩展字符串以方便操作
    int size = listAddr.size();
    for (int i = 0; i < size; i++)
    {
        pos = listAddr.find(pattern, i);
        if (pos < size)
        {
            string s = listAddr.substr(i, pos - i);
            if(!s.empty()){
                result.push_back(s);
            }
            i = pos + pattern.size() - 1;
        }
    }
    return result;
}

string CUtils::toString(const float a_value, const int n)
{
    ostringstream out;
    out << setiosflags(ios::fixed) << setprecision(n) << a_value;
    return out.str();
}
string CUtils::toString(const double a_value, const int n)
{
    ostringstream out;
    out << setiosflags(ios::fixed) << setprecision(n) << a_value;
    return out.str();
}

// 获取UUID
string CUtils::getOnlyId()
{
    return QUuid::createUuid().toString().toStdString();
}

// 获取UUID
string CUtils::getLongOnlyId()
{
    return QUuid::createUuid().toString().toStdString();
}

string CUtils::SubString(string src, string findValue, string stopName)
{
	string ret;
	if(findValue.empty()){
		int startPos =  0;
		if(stopName.empty()){
			return "";
		}
		if(src.find(stopName,startPos) != src.npos){
			int stopPos = src.find(stopName,startPos);
			ret = src.substr(startPos, stopPos-startPos);
		}
		return ret;
	}
	if(src.find(findValue) != src.npos){
		int startPos =  src.find(findValue) + findValue.length();
		if(stopName.empty()){
			startPos-= findValue.length();
			ret = src.substr(startPos);
			return ret;
		}
		if(src.find(stopName,startPos) != src.npos){
			int stopPos = src.find(stopName,startPos);
			ret = src.substr(startPos, stopPos-startPos);
		}

	}
	return ret;

}

// 字符串替换
void CUtils::replace_all_distinct(string& str, string old_value, string new_value)
{
	for(string::size_type  pos(0);  pos!=string::npos;  pos+=new_value.length())
	{
		if(  (pos=str.find(old_value,pos)) != string::npos  )
		{
			str.replace(pos,old_value.length(),new_value);
		}
		else
		{
			break;
		}
	}
	return;
}

// 字符删除
void CUtils::removeChar(string &str, char removeStr)
{
	str.erase(std::remove_if(str.begin(), str.end(), [removeStr](char ch) {return ch == removeStr; }), str.end());
}

// 字符串删除
void CUtils::removeString(string &str, string removeStr)
{
	while(1){
		string::size_type pos  = str.find(removeStr);
		if(pos == str.npos){
			break;
		}
		str = str.erase(pos, removeStr.length());
	}
}

// 统计字符串出现次数
unsigned long CUtils::StatisticsStrCount(string src, string statisticsStr)
{

	unsigned long count = 0;
	unsigned long pos = 0;
	while(true){
		if(src.find(statisticsStr, pos) != src.npos){
			pos += src.find(statisticsStr, pos)+1;
			count++;
			if(pos >= src.length()){
				break;
			}
		} else {
			break;
		}
	}
	return count;
}
// 时间字符串转时间戳
long CUtils::timerStrToTimeStamp(string timerStr)
{
	if(timerStr.empty()){
		return 0;
	}
	struct tm tm;
	memset(&tm, 0, sizeof(tm));

	sscanf(timerStr.c_str(), "%d-%d-%d %d:%d:%d",
		   &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
		   &tm.tm_hour, &tm.tm_min, &tm.tm_sec);

	tm.tm_year -= 1900;
	tm.tm_mon--;
	return mktime(&tm);
}

static int b64idx(int c) {
	if (c < 26) {
		return c + 'A';
	}
	else if (c < 52) {
		return c - 26 + 'a';
	}
	else if (c < 62) {
		return c - 52 + '0';
	}
	else {
		return c == 62 ? '+' : '/';
	}
}

static int b64rev(int c) {
	if (c >= 'A' && c <= 'Z') {
		return c - 'A';
	}
	else if (c >= 'a' && c <= 'z') {
		return c + 26 - 'a';
	}
	else if (c >= '0' && c <= '9') {
		return c + 52 - '0';
	}
	else if (c == '+') {
		return 62;
	}
	else if (c == '/') {
		return 63;
	}
	else {
		return 64;
	}
}


static void b64enc(string &dst, const unsigned char *p, int n) {
	char buf[4];
	int i = 0;
	for (i = 0; i < n; i += 3) {
		int a = p[i], b = i + 1 < n ? p[i + 1] : 0, c = i + 2 < n ? p[i + 2] : 0;
		buf[0] = b64idx(a >> 2);
		buf[1] = b64idx((a & 3) << 4 | (b >> 4));
		buf[2] = b64idx((b & 15) << 2 | (c >> 6));
		buf[3] = b64idx(c & 63);
		if (i + 1 >= n) buf[2] = '=';
		if (i + 2 >= n) buf[3] = '=';
		dst += string(buf,4);
	}
}

static void b64dec(const char *src, int n, string &dst) {
	const char *end = src + n;
	while (src + 3 < end) {
		int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]),
			d = b64rev(src[3]);
		dst += (a << 2) | (b >> 4);
		if (src[2] != '=') {
			dst += (b << 4) | (c >> 2);
			if (src[3] != '=') {
				dst += (c << 6) | d;
			}
		}
		src += 4;
	}
}

static long b64dec(const char *src, int n, char *dst) {
	const char *end = src + n;
	long len = 0;
	while (src + 3 < end) {
		int a = b64rev(src[0]), b = b64rev(src[1]), c = b64rev(src[2]),
			d = b64rev(src[3]);
		dst[len++] = (a << 2) | (b >> 4);
		if (src[2] != '=') {
			dst[len++] = (b << 4) | (c >> 2);
			if (src[3] != '=') {
				dst[len++] = (c << 6) | d;
			}
		}
		src += 4;
	}
	return len;
}

void CUtils::deleteBase64Text(string& src, const string &deleText)
{
	if(deleText.find("*") == string::npos){
		size_t  pos = 0;
		while ((pos = src.find(deleText)) != std::string::npos) {
			src.erase(pos, deleText.size());
		}
		return;
	}

	//字符串分割函数
	std::vector<std::string> textList = split(deleText, "*");
	if(textList.empty()){
		return;
	}
	int deleteI = 1;
	int end_pos = std::string::npos;
	size_t start_pos = src.find(textList[0]);
	if(start_pos == std::string::npos){
		return;
	}
	if(textList.size() == 1){
		// 只有一个，表示删除后面所有
		src.erase(start_pos, end_pos);
		return;
	}
	while(deleteI < textList.size()){
		end_pos = src.find(textList[deleteI], start_pos);
		if(end_pos == std::string::npos){
			src.erase(start_pos, textList[deleteI].size());
			//printf("src=%s\n", src.c_str());
			return;
		}
		//printf("start_pos=%u, end_pos=%u\n", start_pos, end_pos);
		//printf("src=%s\n", src.c_str());
		src.erase(start_pos, end_pos);
		//printf("src=%s\n", src.c_str());
		start_pos = src.find(textList[deleteI]);
		if(deleteI+1 >= textList.size()){
			src.erase(start_pos, textList[deleteI].size());
			//printf("src=%s\n", src.c_str());
		}
		deleteI++;
	}
}


// 编码为base64
void CUtils::encodeBase64(const char *src, string &dst)
{
	b64enc(dst,(const unsigned char *)src, strlen(src));

}

// 编码为base64
void CUtils::encodeBase64(const char *src, int srcLen, string &dst)
{
	b64enc(dst,(const unsigned char *)src, srcLen);
}

// 文件编码为base64
void CUtils::encodeFileToBase64(string filePath, string &dst)
{

    QFileInfo fileInfo(filePath.c_str());
    if (!fileInfo.exists()){
		return;
	}
	ifstream  file1;
	file1.open(filePath.c_str(),ios::in | ios::binary);
	if(!file1.is_open()){
		return;
	}
	file1.seekg(0,ios::end);
    long long len = file1.tellg();
    file1.seekg(0,ios::beg);

    char *src = new char[len];
	file1.read(src, len);
	file1.close();

	b64enc(dst,(const unsigned char *)src, len);

	delete [] src;
	src = nullptr;

}

// 解码base64
void CUtils::decodeBase64(const char *src, string &dst)
{
	b64dec(src,strlen(src), dst);
}

// 解码base64到文件
bool CUtils::decodeBase64ToFile(const char *src, string filePath)
{
	if(strlen(src) <= 0){
		return false;
	}
	string pdstDir = filePath.substr(0,filePath.rfind("/"));
	string mkdirCmd ="mkdir -p ";
	mkdirCmd.append (pdstDir);

    QFileInfo fileInfo(filePath.c_str());
    if (!fileInfo.exists())
	{
		if(system(mkdirCmd.c_str()) == -1){
			printf("error:%s",mkdirCmd.c_str());
			return false;
		}
	}
	string strSrc(src);
	deleteBase64Text(strSrc, "data:*;base64,");
	char *dst = new char[strSrc.size()];
	long len = b64dec(strSrc.c_str(), strSrc.size(), dst);

	ofstream  file1;
	file1.open(filePath.c_str(),ios::out | ios::binary);
	file1.write(dst, len);
	file1.flush();
	file1.close();
	delete []dst;
	dst = nullptr;
	return true;
}


/**
 * 判断路径是目录还是文件
 * ret 0 目录 ret 1文件 ret -1 不存在 ret -2失败
 */
static int pathIsFile(const char* filename)
{
    struct stat info;
    int r=stat(filename, &info);
    if(r==0)
    {
        if(_S_IFDIR == info.st_mode)
        	return 0;
        else
        	return 1;
    }else
    {
        if( errno==ENOENT)
        	return -1;
        else
        	return -2;
    }
}

// 删除文件或文件夹
void CUtils::deletePath(const char* path)
{
	if(pathIsFile(path) == 1){
		remove(path);
		return;
	} else if(pathIsFile(path) < 0){
		return;
	}

    QDir pDir(path);
	struct dirent *dmsg;
	char szFileName[128];
	char szFolderName[128];

	strcpy(szFolderName, path);
    strcat(szFolderName, "/%s");
    // 删除目录下的所有文件和目录
    pDir.removeRecursively();
}

// 路径检查，不存在就创建
void CUtils::pathInspect(const string &path)
{
	string filePath;
    for(int i = 0; i <  path.length(); i++)
    {
        if(path[i] == '/' && i != 0)
    	{
    		filePath = path.substr(0,i);
            QFileInfo fileInfo(filePath.c_str());
            if(!fileInfo.exists())
                QDir().mkdir(filePath.c_str());
    	}
    }
}

int CUtils::calCpuoccupy (CPU_OCCUPY *o, CPU_OCCUPY *n)
{
    unsigned long od, nd;
    unsigned long id, sd;
    int cpu_use = 0;

    od = (unsigned long) (o->user + o->nice + o->system +o->idle);//第一次(用户+优先级+系统+空闲)的时间再赋给od
    nd = (unsigned long) (n->user + n->nice + n->system +n->idle);//第二次(用户+优先级+系统+空闲)的时间再赋给od

    id = (unsigned long) (n->user - o->user);    //用户第一次和第二次的时间之差再赋给id
    sd = (unsigned long) (n->system - o->system);//系统第一次和第二次的时间之差再赋给sd
    if((nd-od) != 0)
    cpu_use = (int)((sd+id)*10000)/(nd-od); //((用户+系统)乖100)除(第一次和第二次的时间差)再赋给g_cpu_used
    else cpu_use = 0;
    //printf("cpu: %u\n",cpu_use);
    return cpu_use;
}

bool CUtils::getCpuoccupy (CPU_OCCUPY *cpust) //对无类型get函数含有一个形参结构体类弄的指针O
{
    FILE *fd;
    int n;
    char buff[256];
    CPU_OCCUPY *cpu_occupy;
    cpu_occupy=cpust;

    fd = fopen ("/proc/stat", "r");
    if(fd == NULL){
    	return false;
    }
    fgets (buff, sizeof(buff), fd);

    sscanf (buff, "%s %u %u %u %u", cpu_occupy->name, &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle);

    fclose(fd);
    return true;
}



// 获取文件大小
long long CUtils::get_file_size(const string filename)
{
    ifstream in(filename, ifstream::ate | ifstream::binary);
    return in.tellg();
}


BASELIB_END_NAMESPACE
